﻿using Helper.Models;
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;
using System.Xml;


namespace Helper
{
    public class PrintHelper : PrintHelperBase
    {
        enum DocType
        {
            Invoice, Statement, StockTaking
        }
        int noOfPages;
        int itemCount;
        DocType docType;
        int entriesPerPage;
        Object workObject;
        int startYIndex;
        public PrintHelper(FeesStatementModel statement)
        {
            docType = DocType.Statement;
            workObject = statement;
            InitValues(statement.Transactions);
            GetFixedDocument(Helper.Properties.Resources.Statement);
            GenerateDocument();
        }

        private void InitValues(IEnumerable collection)
        {
            startYIndex = 318;
            noOfPages = 1;
            itemCount = 0;
            FixedDocSeq = new FixedDocument();
            entriesPerPage = 25;
            if (docType == DocType.StockTaking)
                entriesPerPage = 27;
            foreach (Object o in collection)
                itemCount++;
            noOfPages = itemCount / entriesPerPage;
            if ((itemCount % entriesPerPage) > 0)
                noOfPages++;
        }

        /// <summary>
        /// Creates a Fixed Document from XAML Resource File
        /// </summary>
        /// <param name="pathToXamlFile"></param>

        private void GetFixedDocument(string fileContent)
        {
            FixedDocument doc = new FixedDocument();
            FixedPage page = null;

            PageContent pageContent = new PageContent();
            for (int i = 1; i <= noOfPages; i++)
            {
                StringReader stringReader = new StringReader(fileContent);
                XmlReader xmlReader = XmlReader.Create(stringReader);
                page = XamlReader.Load(xmlReader) as FixedPage;

                page.Margin = new Thickness(0);
                pageContent = new PageContent();
                pageContent.Margin = new Thickness(0);
                page.MaxWidth = 793.76;
                page.MinHeight = 1122.56;
                ((IAddChild)pageContent).AddChild(page);
                doc.Pages.Add(pageContent);
            }
            FixedDocSeq = doc;
            FixedDocSeq.DocumentPaginator.PageSize = new Size(793.76, 1122.56);
        }

        private void AddText(int pageNo, string text, string fontName, double fontSize, bool isBold, double rotateAngle, Color fontColor, double left, double top)
        {

            TextBlock text1 = new TextBlock();
            text1.TextWrapping = TextWrapping.NoWrap;
            text1.MaxWidth = 340;
            text1.MaxHeight = 60;
            text1.FontFamily = new FontFamily(fontName);
            text1.FontSize = fontSize;
            text1.Foreground = new SolidColorBrush(fontColor);
            if (isBold)
                text1.FontWeight = System.Windows.FontWeights.Bold;
            RotateTransform rotateTransform1 =
      new RotateTransform(rotateAngle);
            text1.RenderTransform = rotateTransform1;
            text1.Text = text;
            if (text1.Text.Length > 45)
                text1.Text = text1.Text.Substring(0, 45) + "...";
            Canvas.SetLeft(text1, left);
            Canvas.SetTop(text1, top);

            ((Canvas)FixedDocSeq.
                Pages[pageNo].GetPageRoot(false).Children[0]).Children.Add(text1);
        }
        private void AddText(int pageNo, string text, string fontName, double fontSize, bool isBold, double rotateAngle, Color fontColor, double left, double top, double maxWidth, double maxHeight, TextWrapping wrapping)
        {

            TextBlock text1 = new TextBlock();
            text1.TextWrapping = wrapping;
            text1.MaxWidth = maxWidth;
            text1.MaxHeight = maxHeight;
            text1.FontFamily = new FontFamily(fontName);
            text1.FontSize = fontSize;
            text1.Foreground = new SolidColorBrush(fontColor);
            if (isBold)
                text1.FontWeight = System.Windows.FontWeights.Bold;
            RotateTransform rotateTransform1 =
      new RotateTransform(rotateAngle);
            text1.RenderTransform = rotateTransform1;
            text1.Text = text;
            Canvas.SetLeft(text1, left);
            Canvas.SetTop(text1, top);

            ((Canvas)FixedDocSeq.
                Pages[pageNo].GetPageRoot(false).Children[0]).Children.Add(text1);
        }
        private void AddText(int pageNo, string text, double left, double top)
        {
            AddText(pageNo, text, "Palatino Linotype", 14, false, 0, Colors.Black, left, top);
        }
        private void AddText(int pageNo, string text, double fontSize, double left, double top)
        {
            AddText(pageNo, text, "Palatino Linotype", fontSize, false, 0, Colors.Black, left, top);
        }
        private void AddText(int pageNo, string text, double fontSize, bool isBold, double left, double top)
        {
            AddText(pageNo, text, "Palatino Linotype", fontSize, isBold, 0, Colors.Black, left, top);
        }
        private double GetYPositionFromIndex(int pageNumber, int itemIndex)
        {
            int currIndex = itemIndex - entriesPerPage * pageNumber;
            return startYIndex + currIndex * 22;
        }
        private async void AddCustomerName(int pageNumber)
        {
            string customerName = "";

            switch (docType)
            {
                case DocType.Invoice:
                    customerName = await DataAccess.GetNameOfStudent((workObject as StudentModel).StudentID); break;
                case DocType.Statement:
                    customerName = await DataAccess.GetNameOfStudent((workObject as FeesStatementModel).StudentID); break;
            }
            AddText(pageNumber, customerName, "Palatino Linotype", 14, true, 0, Colors.Black, 450, 104, 300, 200, TextWrapping.Wrap);

        }
        private void AddStatementPeriod(int pageNumber, DateTime startDate, DateTime endDate)
        {
            string text = startDate.ToString("dd-MMM-yyyy") + " to " + endDate.ToString("dd-MMM-yyyy");
            AddText(pageNumber, "Period:", "Segoe UI", 14, false, 0, Colors.Black, 363, 160, 300, 200, TextWrapping.Wrap);
            AddText(pageNumber, text, "Palatino Linotype", 14, true, 0, Colors.Black, 450, 160, 300, 200, TextWrapping.Wrap);

        }
        private void GenerateDocument()
        {
            switch (docType)
            {
                //case DocType.Invoice: { GenerateInvoice(); break; }
                case DocType.Statement: { GenerateStatement(); break; }
                //case DocType.StockTaking: { GenerateStock(); break; }
            }
        }


        private void AddPageNumber(int pageNumber)
        {
            AddText(pageNumber, "Page " + (pageNumber + 1) + "|" + noOfPages, 14, true, 700, 1035);
        }
        private void AddCurrentDateInv(int pageNumber)
        {
            AddText(pageNumber, DateTime.Now.ToString("dd-MMM-yyyy"), 14, true, 620, 65);
        }
        private void AddCurrentDateSta(int pageNumber)
        {
            AddText(pageNumber, DateTime.Now.ToString("dd-MMM-yyyy"), 14, true, 620, 60);
        }

        #region Statement
        private void GenerateStatement()
        {
            for (int pageNo = 0; pageNo < noOfPages; pageNo++)
            {
                AddCustomerName(pageNo);
                AddTransactionsTotal(pageNo);
                AddTransactionItems(pageNo);
                AddPageNumber(pageNo);
                AddCurrentDateSta(pageNo);
                AddStatementPeriod(pageNo, (workObject as FeesStatementModel).StartDate,
                    (workObject as FeesStatementModel).EndDate);
            }
        }
        private void AddTransactionsTotal(int pageNumber)
        {
            int fontSize = 18;
            int xval = 676;

            if ((workObject as FeesStatementModel).TotalAmt.ToString("N2").Length >= 8)
            {
                fontSize = 16;
                xval = 667;
                if ((workObject as FeesStatementModel).TotalAmt.ToString("N2").Length > 10)
                    fontSize = 13;
            }

            if (pageNumber == 0)
                AddText(pageNumber, (workObject as FeesStatementModel).TotalAmt.ToString("N2"), fontSize, true, xval, 935);
            else
                AddText(pageNumber, "-", 18, true, 676, 940);

        }
        private void AddTransactionItems(int pageNumber)
        {
            int startIndex = entriesPerPage * pageNumber;
            int endIndex = entriesPerPage * (pageNumber + 1);
            if (startIndex < 0)
                startIndex = 0;
            if (endIndex > itemCount)
                endIndex = itemCount;

            for (int index = startIndex; index < endIndex; index++)
            {
                AddTransctionItem(pageNumber, index);
            }
        }
        private void AddTransctionItem(int pageNumber, int itemIndex)
        {
            if (itemIndex == 0)
            {
                AddText(pageNumber, "   -", 12, 26, GetYPositionFromIndex(pageNumber, itemIndex));
                AddText(pageNumber, "   -", 12, 126, GetYPositionFromIndex(pageNumber, itemIndex));
                AddText(pageNumber, @"BAlANCE B/F", 12, 300, GetYPositionFromIndex(pageNumber, itemIndex));
                AddText(pageNumber, (workObject as FeesStatementModel).Transactions[itemIndex].TransactionAmt.ToString("N2"), 12, 676, GetYPositionFromIndex(pageNumber, itemIndex));
                return;
            }
            string dt = (workObject as FeesStatementModel).Transactions[itemIndex].TransactionID.ToString();
            if (dt.Contains("-") || dt.Contains(" ") || dt.Contains("."))
            {
                bool found = false;
                decimal dx;
                string[] all = dt.Split(new char[] { '.', ' ', '-' },
                                                           StringSplitOptions.RemoveEmptyEntries);
                foreach (string s in all)
                {
                    if (decimal.TryParse(s, out dx))
                    {
                        if (found)
                            dt += "-" + s;
                        else
                        {
                            found = true; dt = s;
                        }
                    }
                }
                if (!found)
                    dt = (workObject as FeesStatementModel).Transactions[itemIndex].TransactionID.ToString().Split(new char[] { '.', ' ', '-' },
                                                               StringSplitOptions.RemoveEmptyEntries)[1];
            }

            AddText(pageNumber, (workObject as FeesStatementModel).Transactions[itemIndex].DateOfTransaction.ToString("dd - MMM - yyyy"), 12, 26, GetYPositionFromIndex(pageNumber, itemIndex));

            AddText(pageNumber, (workObject as FeesStatementModel).Transactions[itemIndex].Description.ToString(), 12, 300, GetYPositionFromIndex(pageNumber, itemIndex));
            if ((workObject as FeesStatementModel).Transactions[itemIndex].TransactionType == TransactionTypes.Debit)
            {
                AddText(pageNumber, (workObject as FeesStatementModel).Transactions[itemIndex].TransactionAmt.ToString("N2"), 12, 506, GetYPositionFromIndex(pageNumber, itemIndex));
                AddText(pageNumber, "S-" + dt, 12, 126, GetYPositionFromIndex(pageNumber, itemIndex));
            }
            if ((workObject as FeesStatementModel).Transactions[itemIndex].TransactionType == TransactionTypes.Credit)
            {
                AddText(pageNumber, (workObject as FeesStatementModel).Transactions[itemIndex].TransactionAmt.ToString("N2"), 12, 586, GetYPositionFromIndex(pageNumber, itemIndex));
                AddText(pageNumber, "P-" + dt, 12, 126, GetYPositionFromIndex(pageNumber, itemIndex));
            }
            AddText(pageNumber, CalculateBalance(itemIndex), 12, 676, GetYPositionFromIndex(pageNumber, itemIndex));
        }
        private string CalculateBalance(int itemIndex)
        {
            return "";
        }
        #endregion

    }
}

      

          